package qlc.javafx;

import java.util.Scanner;
import java.util.Stack;

public class CalculateExpression {
    public static void main(String[] args) {
        try(Scanner input = new Scanner(System.in);){
            System.out.println("输入一个算术表达式：");
            String expression = input.nextLine();

            double result = operateExpression(expression);
            processFormat(result);
        }
    }
    public static void processFormat(double result) {
        if(result == Double.MIN_NORMAL)
            System.out.println("Invalid Expression");
        else {
            String string = String.valueOf(result);
            if(string.charAt(string.length()-1) == '0')
                System.out.println("Result: "+(int)result);
            else
                System.out.println("Result: "+result);
        }
    }
    public static double operateExpression(String expression) {
        Stack<Double> operandStack = new Stack<>();
        Stack<Character> operatorStack = new Stack<>();

        if(!isExpression(expression))
            return Double.MIN_NORMAL;

        expression = insertBlanks(expression);
        String[] tokens = expression.split("[ ]+");

        if(!isExpression(tokens))
            return Double.MIN_NORMAL;

        for (String s : tokens) {
            switch(s) {
                case "(":operatorStack.push(s.charAt(0));break;
                case ")":while(!operatorStack.isEmpty() && operatorStack.peek() != '(')
                    operation(operandStack, operatorStack);
                    operatorStack.pop();break;
                case "+":
                case "-":while(!operatorStack.isEmpty() && (operatorStack.peek()=='+' ||
                        operatorStack.peek()=='-' || operatorStack.peek()=='*' ||
                        operatorStack.peek()=='/'))
                    operation(operandStack, operatorStack);
                    operatorStack.push(s.charAt(0));break;
                case "*":
                case "/":while(!operatorStack.isEmpty() && (operatorStack.peek()=='*' ||
                        operatorStack.peek()=='/'))
                    operation(operandStack, operatorStack);
                    operatorStack.push(s.charAt(0));break;
                default:operandStack.push(Double.parseDouble(s));
            }
        }
        while(!operatorStack.isEmpty())
            operation(operandStack, operatorStack);

        return operandStack.pop();
    }
    public static void operation(Stack<Double> operandStack, Stack<Character> operatorStack) {
        double op1 = operandStack.pop();
        double op2 = operandStack.pop();
        char op = operatorStack.pop();

        switch (op) {	//执行操作数间的加减乘除运算
            case '+':operandStack.push(op2 + op1);break;
            case '-':operandStack.push(op2 - op1);break;
            case '*':operandStack.push(op2 * op1);break;
            case '/':operandStack.push(op2 / op1);
        }
    }
    public static String insertBlanks(String expression) {
        StringBuffer stringBuffer = new StringBuffer();
        expression = expression.replaceAll(" ", "");
        for (int i = 0; i < expression.length(); i++) {
            if(String.valueOf(expression.charAt(i)).matches("\\."))
                stringBuffer.append(expression.charAt(i));
            else if(i==0 && String.valueOf(expression.charAt(i)).matches("-"))
                stringBuffer.append(expression.charAt(i));
            else if(i>0 && String.valueOf(expression.charAt(i-1)).matches("[\\(\\)\\+-/\\*]")
                    && String.valueOf(expression.charAt(i)).matches("-"))
                stringBuffer.append(expression.charAt(i));
            else if(String.valueOf(expression.charAt(i)).matches("[\\(\\)\\+-/\\*]"))
                stringBuffer.append(" "+expression.charAt(i)+" ");
            else
                stringBuffer.append(expression.charAt(i));	//匹配数字
        }
        return stringBuffer.toString().trim();
    }
    public static boolean isExpression(String expression) {
        StringBuffer stringBuffer = new StringBuffer();

        for (char c : expression.toCharArray()) {
            if(String.valueOf(c).matches("\\."))
                stringBuffer.append(c);
            else if(String.valueOf(c).matches("[\\(\\)\\+-/\\*]"))
                stringBuffer.append(" "+c+" ");
            else
                stringBuffer.append(c);
        }
        String[] tokens = stringBuffer.toString().split("[ ]+");
        return isExpression(tokens);
    }
    public static boolean isExpression(String[] tokens) {
        for (int i = 0; i < tokens.length-2; i++) {
            if(tokens[i].matches("[^\\(\\)\\+-/\\*\\d]"))
                return false;
            if(tokens[i].matches("\\d") && tokens[i+2].matches("\\d"))
                if(tokens[i+1].matches("[^\\+-/\\*]"))
                    return false;
            if(tokens[i].matches("\\d") && tokens[i+1].matches("\\d"))
                return false;
            if(i == tokens.length-3)
                if(tokens[i+1].matches("[^\\(\\)\\+-/\\*\\d]") ||
                        tokens[i+2].matches("[^\\(\\)\\+-/\\*\\d]"))
                    return false;
        }
        int left,right;
        left = right = 0;
        for (String s : tokens) {
            if(s.matches("\\(")) left++;
            if(s.matches("\\)")) right++;
        }
        if(left != right)
            return false;
        if(tokens.length == 2)
            return false;
        if(tokens[tokens.length-1].matches("[^\\d\\)]"))
            return false;
        return true;
    }
}
